#!/usr/bin/perl
# Coded for sigMatch
# Author: Ramakrishnan Kandhan (ramak@cs.wisc.edu)
#
# ====================================================================
# The Apache Software License, Version 1.1
#
# Copyright (c) 2000 The Apache Software Foundation.  All rights
# reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#
# 3. The end-user documentation included with the redistribution,
#    if any, must include the following acknowledgment:
#       "This product includes software developed by the
#        Apache Software Foundation (http://www.apache.org/)."
#    Alternately, this acknowledgment may appear in the software itself,
#    if and wherever such third-party acknowledgments normally appear.
#
# 4. The names "Apache" and "Apache Software Foundation" must
#    not be used to endorse or promote products derived from this
#    software without prior written permission. For written
#    permission, please contact apache@apache.org.
#
# 5. Products derived from this software may not be called "Apache",
#    nor may "Apache" appear in their name, without prior written
#    permission of the Apache Software Foundation.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
# ====================================================================
#
# This software consists of voluntary contributions made by many
# individuals on behalf of the Apache Software Foundation.  For more
# information on the Apache Software Foundation, please see
# <http://www.apache.org/>.
#
# Portions of this software are based upon public domain software
# originally written at the National Center for Supercomputing Applications,
# University of Illinois, Urbana-Champaign.
#

#
# Build the arrays for each of the words.
# Allocation here is greedy but aided by the fact that the allocation is performed using certain heuristics.
# We know that short nonpolymorphic strings and polymorphic signatures are more selective, so put them first 
# and let them have their pick. 
#
# Usage ./sigAlloc.pl <sigFile> <beta> <b-gram File> <outDir>
#

use strict;
use List::Util 'max';

#input params
my $sigF = shift;


#initialize the parameters
my $lengthb = 4;
my $beta = shift; #$beta here is the minimum possible. We could have variable beta depending on least string length
my $num_hash = 1;
my $MaxLLSize = 10;
my $MaxHashSize = 200;
my $fminl = $lengthb + $beta + $num_hash - 1;
my $arrsize = 16**$lengthb;

#open the signatures file
open my $fd,$sigF;
my @lines = <$fd>;
close $fd;
chomp(@lines);


#separate the polymorphic and non-polymorphic signatures
my @psign;
my @npsign;
my $pscount = 0;
my $npscount = 0;
foreach my $li (@lines) {
	my @l = split(/=/,$li);      #这里涉及到特征码的格式问题
	if ($l[1] =~ m/\*|\?|\(|\)|\||\{|\}/) {
		$psign[$pscount++] = $l[1];
	}
	else {
		$npsign[$npscount++] = $l[1];
	}
}

@npsign = sort { length($b) <=> length($a) } @npsign;

#Create a sorted array for np streches
my @npstretch;
my @npsc;
my @spstr;
my $escChar ="z";
foreach my $ps (@psign) {
	my $flag = 0;
	my @parr = split(/\*|\?|\(|\)|\||\{|\}/,$ps);
	my @sparr = sort { length($b) <=> length($a) } @parr;
	my $pushstr = "";
	foreach my $sp(@sparr) {
		if (length($sp) > $fminl) {
			$pushstr = "$pushstr$sp$escChar";
			$flag = 1;
		}
		#push (@npstretch,$sp);
	}
	#push (@npsc,$#sparr+1);
	if ($flag == 1) {
		push (@npsign,$pushstr);
	}
	else {
		push (@spstr,$ps);
	}
}

open my $fd,">npsigns.txt";
foreach my $enp (@npsign) {
	print $fd "$enp\n";
}
close $fd;

open my $fd, ">spsigns.txt";
foreach my $esp (@spstr) {
	print $fd "$esp\n";
}
close $fd;


# finding uniq key  set code must go here 
# but this has already been done and stored in a file.
my $uniqF = shift;
open my $fd,$uniqF;
my @cwords = <$fd>;
close $fd;
chomp(@cwords);

my @scount;
my @sids;
for (my $i=0; $i<=$#cwords; $i++) {
	$scount[$i] = 0;
	$sids[$i] = "";
}

for (my $i=$#npsign; $i>=0; $i--) {
	my $least = max(@scount);
	my $ind = -1;
	my $nxt7;
	for (my $j=0; $j<=$#cwords; $j++) {
		my $word = $cwords[$j];
		if ($npsign[$i] =~ m/$word/) {
			if ($i >= $npscount) {
				my $tm = index($npsign[$i],$word);
				if (index($npsign[$i],$escChar,	$tm+1) - $tm >= $fminl) {
					if ($scount[$j] <= $least) {
						$least=$scount[$j];
						$ind = $j;
						$nxt7= substr($npsign[$i], $tm+4, $beta);
					}
				}
			}
			else {		
				my $tm = index($npsign[$i],$word);
				if (length($npsign[$i])-$tm >=$fminl) {
					if ($scount[$j] <= $least) {
						$least=$scount[$j];
						$ind = $j;
						$nxt7 = substr($npsign[$i], $tm+4, $beta);
					}
				}
			}
		}
	}
	if ($ind >=0 ) {
		$sids[$ind] = "$sids[$ind]$nxt7\n";
		$scount[$ind]++;
	}
}

my $outDir = shift;
open my $fd1, ">sigcounts.txt";
for (my $i=0; $i<=$#cwords; $i++) {
	open $fd,">$outDir/$cwords[$i].txt";
	print $fd "$sids[$i]";
	print $fd1 "$scount[$i]\n";
}
close $fd1;
